package com.insight.datasource.adapter;

import com.insight.entity.DataSource;
import com.insight.entity.MetadataColumn;
import com.insight.entity.MetadataIndex;
import com.insight.entity.MetadataTable;

import java.util.List;

/**
 * T054: 元数据提取器统一接口
 * 定义从不同类型数据库提取元数据的标准方法
 * 采用策略模式,每个数据库类型提供不同的实现
 *
 * 设计原则:
 * - 单一职责: 只负责元数据提取,不涉及业务逻辑
 * - 开闭原则: 新增数据库类型只需添加新实现,无需修改接口
 * - 依赖倒置: 上层服务依赖此接口抽象,而非具体实现
 *
 * 实现类:
 * - OracleMetadataExtractor (T056)
 * - MySQLMetadataExtractor (T058)
 * - SQLServerMetadataExtractor (T060)
 * - PostgreSQLMetadataExtractor (T062)
 * - TiDBMetadataExtractor (T064)
 * - DamengMetadataExtractor (T066)
 *
 * @author Insight Team
 */
public interface MetadataExtractor {

    /**
     * 从数据源提取表列表
     *
     * 功能说明:
     * - 连接到指定数据源
     * - 查询系统元数据视图获取表信息
     * - 支持schema/database过滤
     * - 提取表的基本属性(名称、类型、注释等)
     *
     * 实现要求:
     * - 必须处理连接异常并转换为运行时异常
     * - 必须返回非null列表(空结果返回空列表)
     * - 必须过滤系统表和临时表
     * - 必须正确处理表名大小写(根据数据库规范)
     *
     * @param dataSource 数据源配置信息(包含连接参数)
     * @param schemaFilter schema过滤条件(null表示提取所有schema)
     *                     - Oracle: SCHEMA名称(如HR, SCOTT)
     *                     - MySQL: DATABASE名称(如testdb)
     *                     - SQL Server: SCHEMA名称(如dbo)
     *                     - PostgreSQL: SCHEMA名称(如public)
     * @return 表元数据列表,空结果返回空列表而非null
     * @throws RuntimeException 当数据库连接失败或查询元数据失败时
     */
    List<MetadataTable> extractTables(DataSource dataSource, String schemaFilter);

    /**
     * 从指定表提取列信息
     *
     * 功能说明:
     * - 连接到指定数据源
     * - 查询系统元数据视图获取列详细信息
     * - 提取列的所有属性(名称、类型、长度、精度、可空性等)
     * - 保留列的原始顺序
     *
     * 实现要求:
     * - 必须返回非null列表(空结果返回空列表)
     * - 必须正确设置列的position字段(从1开始递增)
     * - 必须正确识别主键列(isPrimaryKey字段)
     * - 必须正确映射数据库原生类型到标准类型
     * - 必须提取数据类型的长度/精度/标度信息
     *
     * @param dataSource 数据源配置信息
     * @param table 要提取列的表元数据
     * @return 列元数据列表,按position排序,空结果返回空列表而非null
     * @throws RuntimeException 当数据库连接失败或查询元数据失败时
     */
    List<MetadataColumn> extractColumns(DataSource dataSource, MetadataTable table);

    /**
     * 从指定表提取索引信息
     *
     * 功能说明:
     * - 连接到指定数据源
     * - 查询系统元数据视图获取索引详细信息
     * - 提取索引的所有属性(名称、类型、包含的列等)
     * - 识别索引唯一性
     *
     * 实现要求:
     * - 必须返回非null列表(空结果返回空列表)
     * - 必须正确识别主键索引(indexType=PRIMARY)
     * - 必须正确识别唯一索引(indexType=UNIQUE, isUnique=true)
     * - 必须正确处理复合索引(columnNames用逗号分隔)
     * - 必须保留索引列的顺序
     * - 必须提取索引注释(如果数据库支持)
     *
     * @param dataSource 数据源配置信息
     * @param table 要提取索引的表元数据
     * @return 索引元数据列表,空结果返回空列表而非null
     * @throws RuntimeException 当数据库连接失败或查询元数据失败时
     */
    List<MetadataIndex> extractIndexes(DataSource dataSource, MetadataTable table);

    /**
     * 测试数据源连接是否可用
     *
     * 功能说明:
     * - 尝试建立到数据源的连接
     * - 执行简单的验证查询(如SELECT 1)
     * - 关闭连接并释放资源
     *
     * 实现要求:
     * - 必须在finally块中关闭连接
     * - 必须捕获所有异常并返回false,不抛出异常
     * - 必须设置合理的连接超时(建议5秒)
     * - 可以缓存连接测试结果以提高性能
     *
     * @param dataSource 数据源配置信息
     * @return true表示连接成功,false表示连接失败
     */
    boolean testConnection(DataSource dataSource);

    /**
     * 获取数据库版本信息(可选方法,默认返回"未知")
     *
     * 功能说明:
     * - 查询数据库版本号
     * - 用于兼容性检查和日志记录
     *
     * @param dataSource 数据源配置信息
     * @return 数据库版本字符串,如"Oracle Database 19c","MySQL 8.0.28"
     */
    default String getDatabaseVersion(DataSource dataSource) {
        return "未知版本";
    }

    /**
     * 获取当前schema/database名称(可选方法,默认返回null)
     *
     * 功能说明:
     * - 查询当前连接的默认schema/database
     * - 用于自动推断schemaFilter参数
     *
     * @param dataSource 数据源配置信息
     * @return 当前schema/database名称,未知时返回null
     */
    default String getCurrentSchema(DataSource dataSource) {
        return null;
    }
}
